package cc.eddic.practice.concurrency.QiNiuImpl;

import cc.eddic.practice.concurrency.QiNiuLogItem;
import cc.eddic.practice.concurrency.QiNiuLogItemParser;
import lombok.extern.slf4j.Slf4j;
import lombok.val;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class LogItemParserQiNiuScwImpl implements QiNiuLogItemParser {
    /**
     * 解析日志项
     *
     * @param line 日志行
     * @return LogItem 可能为空
     */
    @Override
    public Optional<QiNiuLogItem> parse(String line) {
        val gp = PATTERN_LOG_LINE.matcher(line);
        if (!gp.matches()) {
            log.error("Error parsing line: {}", line);
            return Optional.empty();
        }
        String clientIP = gp.group("clientIP");
        String hitMiss = gp.group("hitMiss");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z", Locale.ENGLISH);
        String responseTime = gp.group("responseTime");
        LocalDateTime timeZone = LocalDateTime.parse(gp.group("timeZone"), formatter);
        String method = gp.group("method");
        String url = gp.group("url");
        String protocol = gp.group("protocol");
        int statuesCode = Integer.parseInt(gp.group("statusCode"));
        long trafficSize = Long.parseLong(gp.group("trafficSize"));
        String referer = gp.group("referer");
        String userAgent = gp.group("userAgent");

        return Optional.of(new QiNiuLogItem(clientIP, hitMiss, responseTime, timeZone, method,
                url, protocol, statuesCode, trafficSize, referer, userAgent));

    }


    private static final Pattern PATTERN_LOG_LINE = Pattern.compile(
            "(?<clientIP>.+) " +
                    "(?<hitMiss>.+) " +
                    "(?<responseTime>\\d+) \\[" +
                    "(?<timeZone>.+)] \"" +
                    "(?<method>\\w+) " +
                    "(?<url>.+) " +
                    "(?<protocol>\\S+?)\" " +
                    "(?<statusCode>\\d+) " +
                    "(?<trafficSize>\\d+) \"" +
                    "(?<referer>.*?)\" \"" +
                    "(?<userAgent>.*)\"", Pattern.UNICODE_CHARACTER_CLASS | Pattern.DOTALL);


}
